//Exported Functions
#ifndef GUARD_BATTLE_AI_MASTER
#define GUARD_BATTLE_AI_MASTER

#define EFFECT_0HKO EFFECT_OHKO
#define GROUNDED 1
#define BATTLE_STATS_NO NUM_BATTLE_STATS

#define AI_SCRIPT_CHECK_BAD_MOVE (1 << 0)
#define AI_SCRIPT_SEMI_SMART (1 << 1)
#define AI_SCRIPT_CHECK_GOOD_MOVE (1 << 2)

// 10 - 28 are not used
#define AI_SCRIPT_ROAMING (1 << 29)
#define AI_SCRIPT_SAFARI (1 << 30)
#define AI_SCRIPT_FIRST_BATTLE (1 << 31)
struct FlingStruct
{
    u8 power;
    u8 effect;
};

extern const struct FlingStruct gFlingTable[];

struct AIScript
{
	u16 atkSpecies;
	u16 defSpecies;
	u16 atkAbility;
    u16 defAbility;

	u8 atkItemEffect;
	u8 defItemEffect;
	u16 defItem;
	u16 atkItem;

	u8 atkItemQuality;
	u8 defItemQuality;
	u32 atkStatus1;
	u32 defStatus1;
	u32 atkStatus2;
	u32 defStatus2;
	u32 atkStatus3;
	u32 defStatus3;
	u8 atkGender;
	u8 defGender;

	u16 atkAttack;
	u16 atkDefense;
	u16 atkSpeed;
	u16 atkSpAtk;
	u16 atkSpDef;

	u16 defAttack;
	u16 defDefense;
	u16 defSpeed;
	u16 defSpAtk;
	u16 defSpDef;

	u8 bankAtkPartner;
	u8 bankDefPartner;
    u16 atkPartnerAbility;
    u16 defPartnerAbility;

	u8 foe1;
	u8 foe2;
	u16 partnerMove;
	bool8 partnerHandling;
};

//real function
u8 AI_BattleAI_ChooseMoveOrAction(void);
void AI_AI_TrySwitchOrUseItem(void);
//end
s8 AI_GetMostSuitableMonToSwitchIntoScore(void);
u8 CalcMostSuitableMonToSwitchInto(void);
void ResetBestMonToSwitchInto(u8 bank);
void RemoveBestMonToSwitchInto(u8 bank);
u32 WildMonIsSmart(u8 bank);
void PopulateAIScriptStructWithBaseAttackerData(struct AIScript* data, u8 bankAtk);
void PopulateAIScriptStructWithBaseDefenderData(struct AIScript* data, u8 bankDef);
void LoadBattlersAndFoes(u8* battlerIn1, u8* battlerIn2, u8* foe1, u8* foe2);
void TryTempMegaEvolveBank(u8 bank, struct BattlePokemon* backupMon, u16* backupSpecies, u16* backupAbility);
void TryRevertTempMegaEvolveBank(u8 bank, struct BattlePokemon* backupMon, u16* backupSpecies, u16* backupAbility);
void ShouldDoAIShiftSwitch(void);

//Functions Hooked In
void BattleAI_HandleItemUseBeforeAISetup(void);
u8 AI_GetMostSuitableMonToSwitchInto(void);
bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng);
bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent);

u8 AIScript_Negatives(const u8 bankAtk, const u8 bankDef, const u16 move, const u8 originalViability, struct AIScript*);
u8 AIScript_SemiSmart(const u8 bankAtk, const u8 bankDef, const u16 move, const u8 originalViability, struct AIScript*);
u8 AIScript_Positives(const u8 bankAtk, const u8 bankDef, const u16 move, const u8 originalViability, struct AIScript*);
u8 AIScript_Partner(const u8 bankAtk, const u8 bankAtkPartner, const u16 originalMove, const u8 originalViability, struct AIScript*);
u8 AIScript_Roaming(const u8 bankAtk, const u8 bankDef, const u16 move, const u8 originalViability, struct AIScript*);
u8 AIScript_Safari(const u8 bankAtk, const u8 bankDef, const u16 move, const u8 originalViability, struct AIScript*);
u8 AIScript_FirstBattle(const u8 bankAtk, const u8 bankDef, const u16 move, const u8 originalViability, struct AIScript*);

//Exported Constants
#define AI_ACTION_DONE          0x0001
#define AI_ACTION_FLEE          0x0002
#define AI_ACTION_WATCH         0x0004
#define AI_ACTION_DO_NOT_ATTACK 0x0008
#define AI_ACTION_UNK5          0x0010
#define AI_ACTION_UNK6          0x0020
#define AI_ACTION_UNK7          0x0040
#define AI_ACTION_UNK8          0x0080

#define SWITCHING_INCREASE_KO_FOE 4
#define SWITCHING_INCREASE_RESIST_ALL_MOVES 4
#define SWITCHING_INCREASE_REVENGE_KILL 2 //Can only happen if can KO in the first place
#define SWITCHING_INCREASE_WALLS_FOE 2 //Can only wall if no Super-Effective moves against foe
#define SWITCHING_INCREASE_HAS_SUPER_EFFECTIVE_MOVE 1
#define SWITCHING_INCREASE_CAN_REMOVE_HAZARDS 10

#define SWITCHING_DECREASE_WEAK_TO_MOVE 1

#define SWITCHING_SCORE_MAX (SWITCHING_INCREASE_KO_FOE + SWITCHING_INCREASE_RESIST_ALL_MOVES + SWITCHING_INCREASE_REVENGE_KILL)
extern  u8 sBattler_AI;
#define gBankAttacker sBattler_AI
#define gBankTarget gBattlerTarget
#define umodsi(a,b) a%b

#endif